package com.dxf.securitys.config;


import com.dxf.common.utils.RedisUtil;
import com.dxf.securitys.filter.TokenAuthenticationFilter;
import com.dxf.securitys.filter.TokenLoginFilter;
import com.dxf.securitys.imagecode.CaptchaCodeFilter;
import com.dxf.securitys.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.servlet.http.HttpSessionListener;
import java.util.Arrays;

/**
 * Security配置类
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private TokenManager tokenManager;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CaptchaCodeFilter captchaCodeFilter;


    /**
     * 配置设置
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //解决springSecurty使用X-Frame-Options防止网页被Frame
        http.headers().frameOptions().disable();
        //允许跨域访问
        http.cors().configurationSource(corsConfigurationSource())
                .and().addFilterBefore(captchaCodeFilter, UsernamePasswordAuthenticationFilter.class);;

      http.exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedEntryPoint())
                .accessDeniedHandler(new CustomAccessDeineHandler())
                .and().csrf().disable()
                .authorizeRequests()
              .antMatchers("/open/**", "/swagger-resources/**","/druid/**",
                      "/webjars/**", "/v2/**", "/swagger-ui.html", "/doc.html").permitAll()
                .anyRequest().authenticated()
                .and().logout().logoutUrl("/admin/logout")
                .addLogoutHandler(new TokenLogoutHandler(tokenManager, redisUtil)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisUtil))
                .addFilter(new TokenAuthenticationFilter(authenticationManager(), tokenManager, redisUtil))
                .httpBasic();

    }


    /**
     * 强散列哈希加密实现
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder()
    {
        return new BCryptPasswordEncoder();
    }

    /**
     * 密码处理
     *
     * @param auth
     * @throws Exception
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    /**
     *Security推荐的跨域配置
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfigurationSource source =   new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");    //同源配置，*表示任何请求都视为同源，若需指定ip和端口可以改为如“localhost：8080”，多个以“，”分隔；
        corsConfiguration.addAllowedHeader("*");//header，允许哪些header，本案中使用的是token，此处可将*替换为token；
        corsConfiguration.addAllowedMethod("*");    //允许的请求方法，PSOT、GET等
        corsConfiguration.setAllowCredentials(true);//允许携带cookie
        ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允许跨域访问的url
        return source;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/webjars/**");
    }

}